/* 
* Copyright (c) Harry Pierson. 
*
* This source code is subject to terms and conditions of the Microsoft 
* Permissive License. A copy of the license can be found in the License.html 
* file at the root of this distribution. If you cannot locate the  Microsoft 
* Permissive License, please send an email to harry@devhawk.net. By using this 
* source code in any fashion, you are agreeing to be bound by the terms of the 
* Microsoft Permissive License.
* 
* You must not remove this notice, or any other, from this software.
*/

using System;
using System.IO;

namespace HawkWiki.SampleWiki
{
	public abstract class WikiDataProvider
	{
		public class VersionInfo
		{
			private string _versionName;
			public  string VersionName { get { return _versionName; } }
			private DateTime _versionTimestamp;
			public  DateTime VersionTimestamp { get { return _versionTimestamp; } }

			public VersionInfo(string name, DateTime timestamp)
			{
				_versionName = name;
				_versionTimestamp = timestamp;
			}
		}

		private static WikiDataProvider _dataProvider = null;
		public  static WikiDataProvider Instance
		{
			get
			{
				if (_dataProvider == null)
					_dataProvider = new FileDataProvider();
				return _dataProvider;
			}
		}

		
		public abstract bool CheckPageExists(string pageName);
		public abstract VersionInfo[] GetPageHistory(string pageName);
		public abstract StreamReader GetPageContent(string pageName);
		public abstract StreamReader GetPageVersionContent(string pageName, string versionName, out DateTime timestamp);
		public abstract void UpdatePageContent(string pageName, string content);

		public abstract void CacheType(string pageName, Type handlerType);
		public abstract Type GetCachedType(string pageName);
	}

	public class FileDataProvider : WikiDataProvider
	{
		private static string WikiPageDirectory
		{
            get { return System.Web.Hosting.HostingEnvironment.MapPath("~/App_Data"); }

		}

		private static string ArchiveDirectory
		{
			get
			{
				string path = Path.Combine(WikiPageDirectory, "Archive");
				if (!Directory.Exists(path))
					Directory.CreateDirectory(path);

				return path;
			}
		}

		private static string GetWikiFilename(string pageName)
		{
			return Path.Combine(WikiPageDirectory, Path.ChangeExtension(pageName, ".wiki"));
		}


		public override bool CheckPageExists(string pageName) 
		{ 
			return File.Exists(Path.Combine(WikiPageDirectory, string.Format("{0}.wiki", pageName)));
		}

		public override VersionInfo[] GetPageHistory(string pageName) 
		{ 
			string[] arFiles = Directory.GetFiles(ArchiveDirectory, string.Format("{0}-*.wiki", pageName));
			Array.Sort(arFiles);
			Array.Reverse(arFiles);

			VersionInfo[] arVersions = new VersionInfo[arFiles.Length];

			for (int i = 0; i < arFiles.Length; i++)
			{
				arVersions[i] = new VersionInfo(
					Path.GetFileNameWithoutExtension(arFiles[i]), 
					File.GetLastWriteTime(arFiles[i]));
			}
			return arVersions;

		}

		public override StreamReader GetPageContent(string pageName) 
		{ 
			string path = GetWikiFilename(pageName);
			if (!File.Exists(path))
				return null;

			return new StreamReader(path);
		}

		public override StreamReader GetPageVersionContent(string pageName, string versionName, out DateTime timestamp) 
		{ 
			string path = Path.Combine(ArchiveDirectory, string.Format("{0}.wiki", versionName));
			timestamp = File.GetLastWriteTime(path);
			return new StreamReader(path);
		}

		public override void UpdatePageContent(string pageName, string content)
		{
			string path = GetWikiFilename(pageName);

			//if file exists, archive it
			if (File.Exists(path))
			{
				//read in existing file
				StreamReader sr = File.OpenText(path);
				string existingText = sr.ReadToEnd();
				sr.Close();

				//if they match, ignore the save request
				if (content == existingText)
					return;

				//move the existing file to the archive directory and add the time to the filename
				DateTime dt = File.GetLastWriteTime(path);
				string toPath = Path.Combine(ArchiveDirectory, string.Format("{0}-{1:yyyy-MM-dd-HH-mm-ss}.wiki", pageName, dt));
				File.Move(path, toPath);
			}

			StreamWriter sw = File.CreateText(path);
			sw.Write(content);
			sw.Close();
		}

		public override void CacheType(string pageName, Type handlerType)
		{
			System.Web.HttpContext.Current.Cache.Insert(
				"CompiledWikiPage_" + pageName,
				handlerType, 
				new System.Web.Caching.CacheDependency(GetWikiFilename(pageName)));
		}

		public override Type GetCachedType(string pageName)
		{
			return (Type)System.Web.HttpContext.Current.Cache["CompiledWikiPage_" + pageName];
		}


	}
}
